package com.example.springboot3demo.config;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * RabbitMQ配置类
 * 
 * 该类负责配置RabbitMQ的相关组件，包括：
 * 1. 消息队列（Queue）
 * 2. 交换机（Exchange）
 * 3. 绑定关系（Binding）
 * 4. 消息模板（RabbitTemplate）
 * 5. 消息转换器（MessageConverter）
 * 
 * 使用TopicExchange实现灵活的路由机制
 */
@Configuration
public class RabbitMQConfig {
    
    /** 默认队列名称 */
    public static final String QUEUE_NAME = "demo.queue";
    
    /** 默认交换机名称 */
    public static final String EXCHANGE_NAME = "demo.exchange";
    
    /** 默认路由键 */
    public static final String ROUTING_KEY = "demo.routing.key";
    
    /** 方法同步交换机名称 */
    public static final String METHOD_SYNC_EXCHANGE = "method.sync.exchange";
    
    /** 方法同步队列名称 */
    public static final String METHOD_SYNC_QUEUE = "method.sync.queue";
    
    /** 方法同步路由键 */
    public static final String METHOD_SYNC_ROUTING_KEY = "method.sync.routing.key";
    
    /**
     * 声明一个持久化队列
     * 
     * @return Queue对象
     */
    @Bean
    public Queue queue() {
        // 第二个参数durable设置为true，表示队列是持久化的，
        // 即使RabbitMQ服务器重启，队列也不会丢失
        return new Queue(QUEUE_NAME, true);
    }
    
    /**
     * 声明一个Topic类型的交换机
     * 
     * TopicExchange支持通配符路由，提供更灵活的消息路由机制
     * 
     * @return TopicExchange对象
     */
    @Bean
    public TopicExchange exchange() {
        return new TopicExchange(EXCHANGE_NAME);
    }
    
    /**
     * 声明方法同步交换机
     * 
     * @return TopicExchange对象
     */
    @Bean
    public TopicExchange methodSyncExchange() {
        return new TopicExchange(METHOD_SYNC_EXCHANGE);
    }
    
    /**
     * 建立队列和交换机之间的绑定关系
     * 
     * @param queue 队列
     * @param exchange 交换机
     * @return Binding对象
     */
    @Bean
    public Binding binding(Queue queue, TopicExchange exchange) {
        // 将队列绑定到交换机上，并指定路由键
        return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY);
    }
    
    /**
     * 声明方法同步队列
     * 
     * @return Queue对象
     */
    @Bean
    public Queue methodSyncQueue() {
        return new Queue(METHOD_SYNC_QUEUE, true);
    }
    
    /**
     * 建立方法同步队列和交换机之间的绑定关系
     * 
     * @param methodSyncQueue 方法同步队列
     * @param methodSyncExchange 方法同步交换机
     * @return Binding对象
     */
    @Bean
    public Binding methodSyncBinding(Queue methodSyncQueue, TopicExchange methodSyncExchange) {
        return BindingBuilder.bind(methodSyncQueue).to(methodSyncExchange).with(METHOD_SYNC_ROUTING_KEY);
    }
    
    /**
     * 配置消息转换器
     * 
     * 使用Jackson2JsonMessageConverter可以将Java对象自动序列化为JSON格式进行传输
     * 接收方会自动将JSON反序列化为对应的Java对象
     * 
     * @return MessageConverter对象
     */
    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }
    
    /**
     * 配置RabbitTemplate
     * 
     * RabbitTemplate是Spring AMQP提供的核心组件，用于发送和接收消息
     * 
     * @param connectionFactory 连接工厂
     * @return RabbitTemplate对象
     */
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        // 设置消息转换器
        rabbitTemplate.setMessageConverter(messageConverter());
        return rabbitTemplate;
    }
}